﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GOFconsole
{
    class Chapter16_StateMethod
    {
        public void StateMethodTest()
        {
            //模型
            Context c = new Context(new ConcreteStateA());
            c.Request();    //不断的请求，同时更改状态
            c.Request();
            c.Request();
            c.Request();

            //DEMO
            Work emergencyProjects = new Work();
            emergencyProjects.Hour = 9;
            emergencyProjects.WritePrograme();
            emergencyProjects.Hour = 12;
            emergencyProjects.WritePrograme();
            emergencyProjects.Hour = 15;
            emergencyProjects.WritePrograme();
            //emergencyProjects.TaskFinished = false;
            emergencyProjects.TaskFinished = true;
            emergencyProjects.Hour = 20;
            emergencyProjects.WritePrograme();
            emergencyProjects.Hour = 22;
            emergencyProjects.WritePrograme();
        }
    }

    #region 模型
    abstract class State    //抽象状态类，定义一个接口以封装与Context的一个特定状态相关的行为
    {
        public abstract void Handle(Context ctx);
    }
    class ConcreteStateA : State  //具体状态，每一个子类实现一个与Context的一个状态相关的行为
    {
        public override void Handle(Context ctx)
        {
            ctx.St = new ConcreteStateB();  //设置A的下一状态是B
        }
    }
    class ConcreteStateB : State  //具体状态，每一个子类实现一个与Context的一个状态相关的行为
    {
        public override void Handle(Context ctx)
        {
            ctx.St = new ConcreteStateA();  //设置B的下一状态是A
        }
    }

    class Context   //维护一个ConcreteState子类的实例，这个实例定义当前状态
    {
        private State st;
        public Context(State st)
        {
            this.st = st;
        }

        public State St //可读写的状态属性，用于读取当前状态和设置新状态
        {
            get { return st; }
            set { st = value; Console.WriteLine("当前状态："+st.GetType().Name); }
        }

        public void Request()
        {
            st.Handle(this);    //对请求做处理，并设置下一状态
        }
    }
    #endregion

    #region DEMO 工作状态
    //抽象状态
    abstract class State_Demo
    {
        public abstract void WriteProgram(Work w);
    }
    //工作类(**不需要在工作类中写上一大堆的时间判断**)
    //如果需要多一个时间段的判断，只要增加一个新的状态，并且改动一下它前一个时间段的状态判断就好了(和链式数组差不多性质)
    class Work
    {
        private State_Demo current;
        public Work()
        {
            current = new ForenoonState();
        }

        public double Hour{get;set;}       //钟点属性，状态转换的依据
        public bool TaskFinished { get; set; } //任务完成属性，是否能下班的依据

        public void SetState(State_Demo s)
        {
            current = s;
        }
        public void WritePrograme()
        {
            current.WriteProgram(this);
        }
    }
    //上午工作类
    class ForenoonState : State_Demo
    {
        public override void WriteProgram(Work w)
        {
            if (w.Hour < 12)
            {
                Console.WriteLine("当前时间: {0}点 上午工作精神百倍。", w.Hour);
            }
            else
            {
                w.SetState(new NoonState());
                w.WritePrograme();
            }
        }
    }
    //中午工作类
    class NoonState : State_Demo
    {
        public override void WriteProgram(Work w)
        {
            if (w.Hour < 13)
            {
                Console.WriteLine("当前时间: {0}点 吃饭时间，犯困。", w.Hour);
            }
            else
            {
                w.SetState(new AfternoonState());
                w.WritePrograme();
            }
        }
    }
    //下午工作类
    class AfternoonState : State_Demo
    {
        public override void WriteProgram(Work w)
        {
            if (w.Hour < 17)
            {
                Console.WriteLine("当前时间: {0}点 下午状态不错。", w.Hour);
            }
            else
            {
                w.SetState(new EveningState());
                w.WritePrograme();
            }
        }
    }
    //晚上工作类
    class EveningState : State_Demo
    {
        public override void WriteProgram(Work w)
        {
            if (w.TaskFinished)
            {
                w.SetState(new RestState());
                w.WritePrograme();
            }
            else
            {
                if (w.Hour < 21)
                {
                    Console.WriteLine("当前时间: {0}点 要加班，好累......", w.Hour);
                }
                else
                {
                    w.SetState(new SleepState());
                    w.WritePrograme();
                }
            }            
        }
    }
    //睡眠类和休息类
    class RestState : State_Demo
    {
        public override void WriteProgram(Work w)
        {
            Console.WriteLine("当前时间: {0}点 下班回家啦。", w.Hour);            
        }
    }
    class SleepState : State_Demo
    {
        public override void WriteProgram(Work w)
        {
            Console.WriteLine("当前时间: {0}点 睡着了。", w.Hour);
        }
    }

    #endregion
}
